<?php

/**
 * Louder Cache
 *
 * LICENSE
 *
 * This source file is subject to the New BSD License that is bundled
 * with this package in the file docs/LICENSE.txt.
 *
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to info@loudertechnology.com so we can send you a copy immediately.
 *
 * @category Louder
 * @package CacheReference
 * @copyright Copyright (c) 2005-2009 Andres Felipe Gutierrez (gutierrezandresfelipe at gmail.com)
 * @license New BSD License
 */

/**
 * Interface a un servidor de Cacheo
 *
 * @category Louder
 * @package CacheReference
 * @copyright Copyright (c) 2005-2009 Andres Felipe Gutierrez (gutierrezandresfelipe at gmail.com)
 * @license New BSD License
 */
class CacheReference {

	/**
	 * Servicio SOAP para comunicacion
	 *
	 * @var SoapClient
	 */
	private $_service;

	/**
	 * URI para servicios del servidor de cacheo
	 *
	 * @var string
	 */
	private static $_serviceURI = "http://louder-cache-service";

	/**
	 * Configuracion del cache
	 *
	 * @var CacheConfiguration
	 */
	private $_configuration;

	/**
	 * Constructor del CacheReference
	 *
	 * @param CacheConfiguration $configuration
	 */
	public function __construct(CacheConfiguration $configuration){
		$location = $configuration->getServerURL();
		if($location==""){
			throw new CacheRefenceException("Debe definir la URL del servidor de cacheo");
		}
		try {
			$this->_service = new SoapClient(null, array(
				'uri' => self::$_serviceURI,
				'location' => $location,
				'trace' => true
			));
			$username = $configuration->getUsername();
			$password = $configuration->getPassword();
			if($this->_sandboxExecute("startTransaction", array($username, $password))==false){
				throw new CacheReferenceException("Usuario/clave incorrectos al autenticar en el servidor de cacheo");
			}
		}
		catch(SoapFault $e){
			throw new CacheReferenceException($e->getMessage());
		}
	}

	/**
	 * Ejecuta una accion en el servicio en una caja de arena
	 *
	 * @param string $actionName
	 * @param array $arguments
	 */
	private function _sandboxExecute($actionName, $arguments=array()){
		try {
			$returnedValue = call_user_func_array(array($this->_service, $actionName), $arguments);
			return unserialize(base64_decode($returnedValue));
		}
		catch(SoapFault $e){
			throw new CacheReferenceException($e->getMessage().$this->_service->__getLastResponse());
		}
	}

	/**
	 * Devuelve el nodo raiz del servidor
	 *
	 * @access public
	 * @return CacheNode
	 */
	public function getRootNode(){
		$node = new CacheNode(0);
		$node->setCacheReference($this);
		return $node;
	}

	/**
	 * Agrega elementos a un nodo
	 *
	 * @access public
	 * @param CacheNode $cacheNode
	 * @param FullyQualifiedName $fqn
	 * @return CacheNode
	 */
	public function addChild(CacheNode $cacheNode, FullyQualifiedName $fqn){
		$node = $this->_sandboxExecute("addChild", array($cacheNode->getId(), $fqn->getPathItems()));
		$node->setCacheReference($this);
		return $node;
	}

	/**
	 * Agrega un atributo a un nodo
	 *
	 * @param CacheNode $cacheNode
	 * @param string $index
	 * @param mixed $value
	 * @return boolean
	 */
	public function addNodeAttribute(CacheNode $cacheNode, $index, $value){
		$serializedValue = base64_encode(serialize($value));
		return $this->_sandboxExecute("addNodeAttribute", array($cacheNode->getId(), $index, $serializedValue));
	}

	/**
	 * Obtener el valor de un atributo del nodo
	 *
	 * @param CacheNode $cacheNode
	 * @param string $index
	 * @return mixed
	 */
	public function getNodeAttribute(CacheNode $cacheNode, $index){
		$value = $this->_sandboxExecute("getNodeAttribute", array($cacheNode->getId(), (string) $index));
		$unserializedValue = unserialize(base64_decode($value));
		return $unserializedValue;
	}

	/**
	 * Realiza una consulta en el arbol
	 *
	 * @access public
	 * @param string $path
	 * @return CacheNode
	 */
	public function query($path){
		$node = $this->_sandboxExecute("query", array($path));
		$node->setCacheReference($this);
		return $node;
	}

	function gt(){
		var_dump($this->_sandboxExecute("gt"));
	}

}